package com.yulp.springboot2task.utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author: yu.lipeng
 * @date: 2018/9/5 15:23
 */
@Component
public class RedisUtil {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 项目模块-缓存前缀, 各自项目前务必加前缀
     */
    public static final String RECEIVE_PREFIX = "mw-order-center-receive:";

    public static final String BUSINESS_PREFIX = "mw-order-center-business:";

    public static final String CLIENT_PREFIX = "mw-order-center-client:";

    public static final String CLOUD_PREFIX = "mw-order-center-cloud:";


    public void set(String key, String value) {
        stringRedisTemplate.opsForValue().set(key, value);
    }

    public String getValue(String key) {
        return this.stringRedisTemplate.opsForValue().get(key);
    }

    /**
     * 向redis里存入数据和设置缓存时间
     *
     * @param key
     * @param value
     * @param timeout
     */
    public void set(String key, String value, long timeout) {
        stringRedisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
    }

    /**
     * 设置过期时间
     *
     * @param key
     * @param timeout
     * @return
     */
    public boolean setKeyExpire(String key, long timeout) {
        return stringRedisTemplate.expire(key, timeout, TimeUnit.SECONDS);
    }

    /**
     * 检查key是否存在，返回boolean值
     *
     * @return
     */
    public boolean hasKey(String key) {
        return stringRedisTemplate.hasKey(key);
    }

    /**
     * 删除对应的value
     *
     * @param key
     */
    public void remove(final String key) {
        if (hasKey(key)) {
            stringRedisTemplate.delete(key);
        }
    }

    /**
     * 原子性操作,并设置过期时间（单位：秒）；
     * 特点：如果不存在则保存数据并返回true;如果存在则返回false;
     *
     * @param key
     * @param value
     * @return
     */
    public boolean setNX(final String key, String value, Long expireTime) {
        boolean result = stringRedisTemplate.opsForValue().setIfAbsent(key, value);
        if (result) {
            stringRedisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
        }
        return result;
    }

    /**
     * 原子性操作
     * 特点：如果不存在则保存数据并返回true;如果存在则返回false;
     *
     * @param key
     * @param value
     * @return
     */
    public boolean setNX(final String key, String value) {
        return stringRedisTemplate.opsForValue().setIfAbsent(key, value);
    }

    /**
     * 自增id生成
     * 规则： 年月日 + 业务编号 + 3位自增编号
     *
     * @param key
     * @param bizNo 业务编号
     * @return
     */
    /*public String generateId(String key, String bizNo) {
        return MwDateUtil.curr8SDateNum() + bizNo + increaseNo(key, 3);
    }*/

    /**
     * 通过redis递增编号（每天从0开始计数）
     *
     * @param cacheKey 缓存key
     * @param size     返回递增数字的位数
     * @return
     */
    /*public String increaseNo(String cacheKey, int size) {
        RedisAtomicLong counter = new RedisAtomicLong(cacheKey, stringRedisTemplate.getConnectionFactory());
        counter.expireAt(MwDateUtil.getTodayEndTime());
        return String.format("%0" + size + "d", counter.incrementAndGet());
    }*/

    /**
     * 业务：分布式锁处理(表级别)
     */
    public boolean checkByKey(String key) {
        //保存10秒,后自动删除
        if (setNX(key, "1", 10L)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 业务：分布式锁处理(订单级别)
     */
    public boolean checkByKeyBill(String key) {
        //保存20秒,后自动删除
        if (setNX(key, "1", 20L)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * hash结构设置值
     * @param key
     * @param hashKey
     * @param value
     * @param expireTime
     */
    public void setHash(String key, String hashKey, String value, long expireTime) {
        stringRedisTemplate.opsForHash().put(key, hashKey, value);
        if (hasKey(key)) {
            stringRedisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
        }
    }

    /**
     * hash结构设置值
     * @param key
     * @param map
     * @param expireTime
     */
    public void setHashAll(String key, Map map, long expireTime) {
        stringRedisTemplate.opsForHash().putAll(key, map);
        stringRedisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
    }

    /**
     * hash结构获取值
     * @param key
     * @param hashKey
     * @return
     */
    public String getHash(String key, String hashKey) {
        Object object = stringRedisTemplate.opsForHash().get(key, hashKey);
        if (object == null) {
            return null;
        }
        return object.toString();
    }

    /**
     * hash结构获取map
     * @param key
     * @return
     */
    public Map getHashMap(String key) {
        Map map = stringRedisTemplate.opsForHash().entries(key);
        if (map == null) {
            return null;
        }
        return map;
    }

}


/**
 * 5种数据结构操作
 * redisTemplate.opsForValue();//操作字符串
 * redisTemplate.opsForHash();//操作hash
 * redisTemplate.opsForList();//操作list
 * redisTemplate.opsForSet();//操作set
 * redisTemplate.opsForZSet();//操作有序set
 * <p>
 * 常用的一些操作:
 * template.opsForValue().set("key", "100",60*10,TimeUnit.SECONDS);//向redis里存入数据和设置缓存时间
 * template.boundValueOps("key").increment(-1);//val做-1操作
 * template.opsForValue().get("key")//根据key获取缓存中的val
 * template.boundValueOps("key").increment(1);//val +1
 * template.getExpire("key")//根据key获取过期时间
 * template.getExpire("key",TimeUnit.SECONDS)//根据key获取过期时间并换算成指定单位
 * template.delete("key");//根据key删除缓存
 * template.hasKey("546545");//检查key是否存在，返回boolean值
 * template.opsForSet().add("red_123", "1","2","3");//向指定key中存放set集合
 * template.expire("red_123",1000 , TimeUnit.MILLISECONDS);//设置过期时间
 * template.opsForSet().isMember("red_123", "1")//根据key查看集合中是否存在指定数据
 * template.opsForSet().members("red_123");//根据key获取set集合
 */